function idat = fsb_realign(idat,sandbox)

% FSB: Realignment GUI
%
% EXAMPLE: idat = fsb_realign(idat,sandbox)
%
% INPUT:
% idat: 4D image data
% sandbox: sandbox experiment struct
%
% OUTPUT:
% sandbox: sandbox experiment data
%
% CALLED BY:
% FSB.m
%
% NOTES:
%
% Copyright 2010 MPI for Biological Cybernetics
% Author: Steffen Stoewer
% License:GNU GPL, no express or implied warranties
%
% $ Revision 1.0
%
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

%~~~~~~~~~~~~~~~~~~~~~~~~~~
% Check input arguments
%~~~~~~~~~~~~~~~~~~~~~~~~~~
if nargin<2
    disp('No data provided, aborting')
    return
end

warning off;
ropts.srt = 5;
ropts.ver = 1;
ropts.do = 1;
ropts.reatype = 1;
ropts.modulate = 0;
ropts.wrap = [0 0 0];
idat_order = [1 2 3 4];
if isfield(sandbox,'wimage')
    wimage = sandbox.wimage;
    sandbox = rmfield(sandbox,'wimage');
end

%~~~~~~~~~~~~~~~~~~~~~~~~~~
% Set GUI up
%~~~~~~~~~~~~~~~~~~~~~~~~~~

realignment_GUI = figure('Visible','off','Position',[100,300,510,300],'Resize','off','Toolbar','none','MenuBar','none','NumberTitle','off','Name','FSB Realignment Toolbox');

%~~~~~~~~~~~~~~~~~~~~~~~~~~
% Add Buttons and edit fields
%~~~~~~~~~~~~~~~~~~~~~~~~~~

uicontrol('Style','Pushbutton',...
    'Position',[20,200,60,25],...
    'String','Run',...
    'TooltipString','Run Realignment',...
    'Callback',{@run_pipeline_Callback});

uicontrol('Style','Pushbutton',...
    'Position',[100,200,60,25],...
    'String','Done',...
    'TooltipString','Return to FSB',...
    'Callback',{@return_FSB_Callback});

if exist('wimage','var')
    h_maskselect = uicontrol('Style','radiobutton','String','Use mask',...
        'Position',[340,270,80,25],'Visible','on',...
        'TooltipString','Select if masking should be done',...
        'Callback',{@Maskselect_Callback});
end

h_wrapt = uicontrol('Style','text',...
    'Position',[340,240,50,20],...
    'String','Wrap','Visible','off');

h_wrap = uicontrol('Style','edit',...
    'Position',[390,240,50,20],...
    'String','0 0 0','Visible','off',...
    'TooltipString','Wrap in x/y/z',...
    'Callback',{@wrap_Callback});

h_modulate = uicontrol('Style','checkbox',...
    'Position',[380,280,100,20],...
    'String','Modulation','Visible','off',...
    'TooltipString','Model signal intensity changes due to normalization',...
    'Callback',{@modulate_Callback});

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% Create a button group for data to work on
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
h1 = uibuttongroup('visible','off','Units','pixels','Position',[20 30 90 150],'Title','Target');

x0 = uicontrol('Style','Radio','String','Volume',...
    'pos',[10 100 70 30],'parent',h1,'HandleVisibility','off');
x1 = uicontrol('Style','Radio','String','Slice x',...
    'pos',[10 70 70 30],'parent',h1,'HandleVisibility','off');
x2 = uicontrol('Style','Radio','String','Slice y',...
    'pos',[10 40 70 30],'parent',h1,'HandleVisibility','off');
x3 = uicontrol('Style','Radio','String','Slice z',...
    'pos',[10 10 70 30],'parent',h1,'HandleVisibility','off');

set(h1,'SelectionChangeFcn',@Get_Realignment_Level_Callback);
set(h1,'SelectedObject',x0);  % Select Volume
set(h1,'Visible','on');

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% Create a button group for Analysis level selection
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

h = uibuttongroup('visible','off','Units','pixels','Position',[130 30 90 150],'Title','Analysis level');

u0 = uicontrol('Style','Radio','String','Trial',...
    'pos',[10 100 70 30],'parent',h,'HandleVisibility','off');
u1 = uicontrol('Style','Radio','String','Run',...
    'pos',[10 70 70 30],'parent',h,'HandleVisibility','off');
u2 = uicontrol('Style','Radio','String','Session',...
    'pos',[10 40 70 30],'parent',h,'HandleVisibility','off');
u3 = uicontrol('Style','Radio','String','Volume',...
    'pos',[10 10 70 30],'parent',h,'HandleVisibility','off');

set(h,'SelectionChangeFcn',@Get_relevant_model_Callback);
set(h,'SelectedObject',u3);  % Select Volume
set(h,'Visible','on');

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% Button group for Method
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

reatype = uibuttongroup('visible','off','Units','pixels','Position',[240 30 250 180],'Title','Method');

r0 = uicontrol('Style','Radio','String','CoM',...
    'pos',[10 100 90 30],'parent',reatype,'HandleVisibility','off');
r1 = uicontrol('Style','Radio','String','DFT',...
    'pos',[10 70 90 30],'parent',reatype,'HandleVisibility','off');
r2 = uicontrol('Style','Radio','String','SPM full',...
    'pos',[10 10 90 30],'parent',reatype,'HandleVisibility','off');
r3 = uicontrol('Style','Radio','String','SPM y only',...
    'pos',[100 130 110 30],'parent',reatype,'HandleVisibility','off');
r4 = uicontrol('Style','Radio','String','SPM 2-step 12-par',...
    'pos',[100 40 110 30],'parent',reatype,'HandleVisibility','off');
r5 = uicontrol('Style','Radio','String','SPM reanorm',...
    'pos',[100 10 110 30],'parent',reatype,'HandleVisibility','off');
r6 = uicontrol('Style','Radio','String','SPM xyz',...
    'pos',[10 40 110 30],'parent',reatype,'HandleVisibility','off');
r7 = uicontrol('Style','Radio','String','SPM 2-step 6-par',...
    'pos',[100 70 110 30],'parent',reatype,'HandleVisibility','off');
r8 = uicontrol('Style','Radio','String','SPM realign means',...
    'pos',[100 100 110 30],'parent',reatype,'HandleVisibility','off');
set(reatype,'SelectionChangeFcn',@Get_reatype_Callback);
set(reatype,'SelectedObject',r0);  % Select CoM
set(reatype,'Visible','on');

%~~~~~~~~~~~~~~~~~~~~~~~~~~
% Wait until user input is done
%~~~~~~~~~~~~~~~~~~~~~~~~~~

set(realignment_GUI,'Visible','on');
axis off;
[eucdist(:,1) corrdist(:,1)] = fsb_diag_euclid(idat,0);

uiwait;

% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% Button callbacks
% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

% ropts: processing options with the fields
%       .srt = 1 : Do spatial preprocessing
%       .ver = 1 : Do realignment
%       .reatype = 1 : Do smoothing


%~~~~~~~~~~~~~~~~~~~~~~~~~~
% SPM selection callback
%~~~~~~~~~~~~~~~~~~~~~~~~~~

    function Get_Realignment_Level_Callback(source,eventdata)

        selstr = get(eventdata.NewValue,'String');
        disp (selstr);
        switch selstr
            case 'Volume'
                ropts.ver = 1;
                idat_order = [1 2 3 4];
                set(r2,'Visible','on');
                set(r3,'Visible','on');
                set(r4,'Visible','on');
                set(r5,'Visible','on');

            case 'Slice x'
                ropts.ver = 2;
                idat_order = [2 1 3 4];
                set(r2,'Visible','off');
                set(r3,'Visible','off');
                set(r4,'Visible','off');
                set(r5,'Visible','off');

            case 'Slice y'
                ropts.ver = 3;
                idat_order = [3 2 1 4];
                set(r2,'Visible','off');
                set(r3,'Visible','off');
                set(r4,'Visible','off');
                set(r5,'Visible','off');

            case 'Slice z'
                ropts.ver = 4;
                idat_order = [1 2 3 4];
                set(r2,'Visible','off');
                set(r3,'Visible','off');
                set(r4,'Visible','off');
                set(r5,'Visible','off');
        end

    end

%~~~~~~~~~~~~~~~~~~~~~~~~~~
% Model selection callback
%~~~~~~~~~~~~~~~~~~~~~~~~~~

    function Get_relevant_model_Callback(source,eventdata)

        selstr = get(eventdata.NewValue,'String');
        disp (selstr);
        switch selstr
            case 'Volume'
                ropts.srt = 8;
                set(r0,'Visible','on');
                set(r1,'Visible','on');
                set(r7,'Visible','on');
            case 'Trial'
                ropts.srt = 3;
                set(r0,'Visible','off');
                set(r1,'Visible','off');
                set(r7,'Visible','off');
            case 'Run'
                ropts.srt = 4;
                set(r0,'Visible','off');
                set(r1,'Visible','off');
                set(r7,'Visible','off');
            case 'Session'
                ropts.srt = 5;
                set(r0,'Visible','off');
                set(r1,'Visible','off');
                set(r7,'Visible','off');
        end

    end

%~~~~~~~~~~~~~~~~~~~~~~~~~~
% Model selection callback
%~~~~~~~~~~~~~~~~~~~~~~~~~~

    function Get_reatype_Callback(source,eventdata)

        selstr = get(eventdata.NewValue,'String');
        disp (selstr);
        switch selstr
            case 'CoM'
                ropts.reatype = 1;
                set(h_wrap,'Visible','off');
                set(h_wrapt,'Visible','off');
                set(h_modulate,'Visible','off');
            case 'DFT'
                ropts.reatype = 2;
                set(h_wrap,'Visible','off');
                set(h_wrapt,'Visible','off');
                set(h_modulate,'Visible','off');
            case 'SPM y only'
                ropts.reatype = 4;
                set(h_wrap,'Visible','on');
                set(h_wrapt,'Visible','on');
                set(h_modulate,'Visible','off');
                
            case  'SPM full'
                ropts.reatype = 5;
                set(h_wrap,'Visible','on');
                set(h_wrapt,'Visible','on');
                set(h_modulate,'Visible','off');
            case 'SPM reanorm'
                ropts.reatype = 6;
                set(h_wrap,'Visible','on');
                set(h_wrapt,'Visible','on');
                set(h_modulate,'Visible','on');
            case 'SPM 2-step 12-par'
                ropts.reatype = 7;
                set(h_wrap,'Visible','on');
                set(h_wrapt,'Visible','on');
                set(h_modulate,'Visible','on');
                %             case 'Demon' % currently not supported, coming in future
                %             versions
                %                 ropts.reatype = 8;
                %                 set(h_wrap,'Visible','off');
                %                 set(h_wrapt,'Visible','off');
                %                 set(h_modulate,'Visible','off');
            case 'SPM 2-step 6-par'
                ropts.reatype = 3;
                set(h_wrap,'Visible','on');
                set(h_wrapt,'Visible','on');
                set(h_modulate,'Visible','off');
            case 'SPM xyz'
                ropts.reatype = 8;
                set(h_wrap,'Visible','on');
                set(h_wrapt,'Visible','on');
                set(h_modulate,'Visible','off');
            case 'SPM realign means'
                ropts.reatype = 9;
                set(h_wrap,'Visible','on');
                set(h_wrapt,'Visible','on');
                set(h_modulate,'Visible','off');
        end

    end


%~~~~~~~~~~~~~~~~~~~~~~~~~~
% Run selected options
%~~~~~~~~~~~~~~~~~~~~~~~~~~

    function run_pipeline_Callback(source,eventdata)

        if ropts.ver ==1; % Take whole 3-D volume for realignment

            if ropts.reatype == 1 % CoM
                idat = fsb_realign_3D_ctm(idat,1);
            end

            if ropts.reatype == 2 % DFT
                idat = fsb_realign_dft3D(idat,0.01);
            end

            if ropts.reatype == 3 % SPM 6-par
                ropts.rp = 5;
                [idat sandbox] = fsb_realign_SPM(idat,sandbox,ropts);
            end

            if ropts.reatype == 4 % SPM y
                ropts.rp = 1;
                [idat sandbox] = fsb_realign_SPM(idat,sandbox,ropts);
            end

            if ropts.reatype == 5 % SPM full
                ropts.rp = -1;
                [idat sandbox] = fsb_realign_SPM(idat,sandbox,ropts);
            end

            if ropts.reatype == 6 % case 'Normalize all volumes to first volume'
                ropts.rp = 2;
                %ropts.srt = 8; % put this in here to normalize all images
                [idat sandbox] = fsb_realign_SPM(idat,sandbox,ropts);
            end

            if ropts.reatype == 7 % case 'Realign y and normalize SPM trial-by-trial'
                % do the normalization on a trial-by-trial level
                ropts.rp = 3;
                % 12-parameter realignment in 2nd step
                [idat sandbox] = fsb_realign_SPM(idat,sandbox,ropts);
            end

            %             if ropts.reatype == 8 % Demon % Currently not supported,
            %             coming in future versions of fMRI Sandbox
            %                 idat = fsb_realign_demon3D(idat);
            %             end

            if ropts.reatype == 9 % Realign means
                ropts.rp = 4;
                [idat sandbox] = fsb_realign_SPM(idat,sandbox,ropts);

            end
            
            if ropts.reatype == 8 % SPM xyz
                ropts.rp = -2;
                [idat sandbox] = fsb_realign_SPM(idat,sandbox,ropts);
            end

        else % Take individual slices

            idat = permute(idat,idat_order);

            if ropts.reatype == 1
                idat = fsb_realign_2D_ctm(idat,0);
            end

            if ropts.reatype == 2
                idat = fsb_realign_dft2D(idat,0.001);
            end

            if ropts.reatype == 3
                idat = fsb_realign_2D_corr(idat);
            end

            if ropts.reatype == 4
                ropts.rp = -1;
                [idat sandbox] = fsb_realign_SPM(idat,sandbox,ropts);
            end

            if ropts.reatype == 5
                idat = fsb_coreg_extreme(idat);
            end

            idat = permute(idat,idat_order);

        end

    end


%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% should the images be wrapped during realignment?
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    function wrap_Callback(source,eventdata)
        wrapvector = get(h_wrap,'String');
        wrapvector = str2num(wrapvector);
        ropts.wrap = wrapvector;
    end

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% should the images be wrapped during realignment?
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    function modulate_Callback(source,eventdata)
        if (get(h_modulate,'Value') == get(h_modulate,'Max')) ;
            ropts.modulate = 1;
        else
            ropts.modulate = 0;
        end

    end

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% use mask
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    function Maskselect_Callback(source,eventdata)

        if (get(h_maskselect,'Value') == get(h_maskselect,'Max')) ;
            sandbox.wimage = wimage;
        else
            sandbox = rmfield(sandbox,'wimage');
        end

    end

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% return to FSB
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    function return_FSB_Callback(source,eventdata)
        [eucdist(:,2) corrdist(:,2)] = fsb_diag_euclid(idat,0);
        eucdiff = eucdist(:,1)-eucdist(:,2);
        methodstring = ['Target : ' get(get(h1,'SelectedObject'),'string')...
            ' | ' 'Analysis level : ' get(get(h,'SelectedObject'),'string')...
            ' | ' 'Method : ' get(get(reatype,'SelectedObject'),'string')];
        figure; set(gcf,'Name',methodstring);
        subplot(3,1,1); plot(eucdist);legend('Before realignment','After realignment','Location','SouthEast');
        xlabel('time -> [img]');
        ylabel('Euclidian distance');
        Title('Euclidian distances of volumes from first volume');
        subplot(3,1,2); plot(eucdiff);
        xlabel('time -> [img]');
        ylabel('Delta of Euclidian distances');
        Title('Difference of Euclidian Distances');
        subplot(3,1,3); plot(corrdist);legend('Before realignment','After realignment','Location','SouthWest')
        xlabel('time -> [img]');
        ylabel('Correlation');
        Title('Correlation of images with first volume');


        close(realignment_GUI);
        return;
    end
end
